package xyz.wadewhy.basicstest.juc;

import lombok.extern.slf4j.Slf4j;

/**
 * @ClassName Thread8Lock
 * @Description 经典案例，线程8锁
 * @Author zhongzihao
 * @Date 2021/12/28 1:04 下午
 * @Version 1.0
 **/
@Slf4j(topic = "c.Thread8Lock")
public class Thread8Lock {

    public static void main(String[] args) {
//        lockV1Test();
//        lockV2Test();
//        lockV3Test();
//        lockV4Test();
//        lockV5Test();
//        lockV6Test();
//        lockV7Test();
        lockV8Test();
    }

    /**
     * 假设线程1拿到锁，由于synchronized锁的是成员变量，this对象，类中a，b方法都加了锁。
     * 线程1在调用a方法时，如果没有释放锁资源，线程2依旧是不能调用b方法，处于等待过程
     */
    public static void lockV1Test() {
        LockV1 lockV1 = new LockV1();
        new Thread(() -> {
            log.info("线程1 lockV1 begin");
            lockV1.a();
        }, "线程1 lockV1").start();
        new Thread(() -> {
            log.info("线程2 lockV1 begin");
            lockV1.b();
        }, "线程2 lockV1").start();
    }

    /**
     * 如果线程1先拿到锁，1s后输入a方法日志，然后输出b方法日志
     * 如果线程2先拿到锁，输出b方法日志，1s后输出a方法日志
     * sleep 使线程睡眠，不会放开锁
     */
    public static void lockV2Test() {
        LockV2 lockV2 = new LockV2();
        new Thread(() -> {
            log.info("线程2 lockV2 begin");
            lockV2.b();
        }, "线程2 lockV2").start();
        new Thread(() -> {
            log.info("线程1 lockV2 begin");
            try {
                lockV2.a();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }, "线程1 lockV2").start();
    }

    /**
     * 是成员变量锁，锁的是this
     * 由于c方法没有加锁，因此所有线程都不需要等待就能调用，所以最终的count值不是50000
     */
    public static void lockV3Test() {
        LockV3 lockV3 = new LockV3();
        new Thread(() -> {
            log.info("线程3 lockV3 begin");
            lockV3.c();
        }, "线程3 lockV3").start();
        new Thread(() -> {
            log.info("线程2 lockV3 begin");
            lockV3.b();
        }, "线程2 lockV3").start();
        new Thread(() -> {
            log.info("线程1 lockV3 begin");
            try {
                lockV3.a();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }, "线程1 lockV3").start();
    }

    /**
     * 是成员变量锁，锁的是this，线程1，线程2不互斥
     * 最终的count不一定是0
     */
    public static void lockV4Test() {
        LockV4 lockV4 = new LockV4();
        LockV4 v4 = new LockV4();
        new Thread(() -> {
            log.info("线程1 lockV4 begin");
            try {
                lockV4.a();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }, "线程1 lockV4").start();
        new Thread(() -> {
            log.info("线程2 lockV4 begin");
            v4.b();
        }, "线程2 lockV4").start();
    }

    /**
     * a方法是静态方法，锁的是类对象
     * b方法是成员方法，锁的是当前对象lockV5
     * 线程1，线程2不互斥，最总的count不一定为0
     */
    public static void lockV5Test() {
        LockV5 lockV5 = new LockV5();
        new Thread(() -> {
            log.info("线程1 lockV5 begin");
            try {
                lockV5.a();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }, "线程1 lockV5").start();
        new Thread(() -> {
            log.info("线程2 lockV5 begin");
            try {
                lockV5.b();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }, "线程2 lockV5").start();
    }

    /**
     * a方法是静态方法，锁的是类对象
     * b方法是静态方法，锁的是类对象
     * 类对象在内存中只有一份
     * 线程1，线程2互斥，count一定为0
     */
    public static void lockV6Test() {
        LockV6 lockV6 = new LockV6();
        new Thread(() -> {
            log.info("线程1 lockV6 begin");
            try {
                lockV6.a();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }, "线程1 lockV6").start();
        new Thread(() -> {
            log.info("线程2 lockV6 begin");
            try {
                lockV6.b();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }, "线程2 lockV6").start();
    }

    /**
     * a方法是静态方法，锁的是类对象
     * b方法是成员方法，锁的是当前对象v7
     * 线程1，线程2不互斥，count不一定为0
     */
    public static void lockV7Test() {
        LockV7 lockV7 = new LockV7();
        LockV7 v7 = new LockV7();
        new Thread(() -> {
            log.info("线程1 lockV7 begin");
            try {
                lockV7.a();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }, "线程1 lockV7").start();
        new Thread(() -> {
            log.info("线程2 lockV7 begin");
            try {
                v7.b();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }, "线程2 lockV7").start();
    }

    /**
     * a方法是静态方法，锁的是类对象
     * b方法是静态方法，锁的是类对象
     * 类对象在内存中只有一份，虽然是调用不同的对象，静态方法随着类创建而创建，用的其实是同一份
     * 线程1，线程2互斥，count一定为0
     */
    public static void lockV8Test() {
        LockV8 lockV8 = new LockV8();
        LockV8 v8 = new LockV8();
        new Thread(() -> {
            log.info("线程1 lockV8 begin");
            try {
                lockV8.a();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }, "线程1 lockV8").start();
        new Thread(() -> {
            log.info("线程2 lockV8 begin");
            try {
                v8.b();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }, "线程2 lockV8").start();
    }
}

@Slf4j(topic = "c.LockV1")
class LockV1 {
    private static final int NUM = 50000;
    private static int count = 0;

    public synchronized void a() {
        for (int i = 0; i < NUM; i++) {
            count++;
        }
        log.debug("lockV1---a: {}" + count);
    }

    public synchronized void b() {
        for (int i = 0; i < NUM; i++) {
            count--;
        }
        log.debug("lockV1---b: {}" + count);
    }
}

@Slf4j(topic = "c.LockV2")
class LockV2 {
    private static final int NUM = 50000;
    private static int count = 0;

    public synchronized void a() throws InterruptedException {
        Thread.sleep(1000);
        for (int i = 0; i < NUM; i++) {
            count++;
        }
        log.debug("lockV2---a: {}" + count);
    }


    public synchronized void b() {
        for (int i = 0; i < NUM; i++) {
            count--;
        }
        log.debug("lockV2---b: {}" + count);
    }
}

@Slf4j(topic = "c.LockV3")
class LockV3 {
    private static final int NUM = 50000;
    private static int count = 0;

    public synchronized void a() throws InterruptedException {
        Thread.sleep(1000);
        for (int i = 0; i < NUM; i++) {
            count++;
        }
        log.debug("lockV3---a: {}" + count);
    }


    public synchronized void b() {
        for (int i = 0; i < NUM; i++) {
            count--;
        }
        log.debug("lockV3---b: {}" + count);
    }

    public void c() {
        for (int i = 0; i < NUM; i++) {
            count++;
        }
        log.debug("lockV3---c: {}" + count);
    }
}

@Slf4j(topic = "c.LockV4")
class LockV4 {
    /*
     * 这里数据弄大点，或者在a方法睡眠
     */
    private final int NUM = 500000000;
    private static int count = 0;

    public synchronized void a() throws InterruptedException {
        for (int i = 0; i < NUM; i++) {
            count++;
        }
        log.debug("lockV4---a: {}" + count);
    }


    public synchronized void b() {
        for (int i = 0; i < NUM; i++) {
            count--;
        }
        log.debug("lockV4---b: {}" + count);
    }
}

@Slf4j(topic = "c.LockV5")
class LockV5 {
    private final static int NUM = 500000000;
    private static int count = 0;

    public static synchronized void a() throws InterruptedException {
        for (int i = 0; i < NUM; i++) {
            count++;
        }
        log.debug("lockV5---a: {}" + count);
    }

    public synchronized void b() throws InterruptedException {
        for (int i = 0; i < NUM; i++) {
            count--;
        }
        log.debug("lockV5---b: {}" + count);
    }
}

@Slf4j(topic = "c.LockV6")
class LockV6 {
    private final static int NUM = 600000000;
    private static int count = 0;

    public static synchronized void a() throws InterruptedException {
        for (int i = 0; i < NUM; i++) {
            count++;
        }
        log.debug("lockV6---a: {}" + count);
    }

    public static synchronized void b() throws InterruptedException {
        for (int i = 0; i < NUM; i++) {
            count--;
        }
        log.debug("lockV6---b: {}" + count);
    }
}

@Slf4j(topic = "c.LockV7")
class LockV7 {
    private final static int NUM = 700000000;
    private static int count = 0;

    public static synchronized void a() throws InterruptedException {
        for (int i = 0; i < NUM; i++) {
            count++;
        }
        log.debug("lockV7---a: {}" + count);
    }

    public synchronized void b() throws InterruptedException {
        for (int i = 0; i < NUM; i++) {
            count--;
        }
        log.debug("lockV7---b: {}" + count);
    }
}

@Slf4j(topic = "c.LockV8")
class LockV8 {
    private final static int NUM = 800000000;
    private static int count = 0;

    public static synchronized void a() throws InterruptedException {
        for (int i = 0; i < NUM; i++) {
            count++;
        }
        log.debug("lockV8---a: {}" + count);
    }

    public static synchronized void b() throws InterruptedException {
        for (int i = 0; i < NUM; i++) {
            count--;
        }
        log.debug("lockV8---b: {}" + count);
    }
}